/**
 * @Author: yuanmanxue <yuanmanxue>
 * @Date:   2017-12-05 04:00:42
 * @Last modified by:   yuanmanxue
 * @Last modified time: 2017-12-27 03:18:26
 */

{
  // var messages = ["喵！", "我是一只会说话的猫！", "回调（callback）非常有趣!"];
  // for (let i = 0; i < messages.length; i++) {
  //   setTimeout(function () {
  //     console.log(messages[i]);
  //   }, i * 1500);
  // }
}
{
  //   var person = {
  //   name: "张三"
  // };
  // var proxy = new Proxy(person, {
  //   get: function(target, property) {
  //     if (property in target) {
  //       return target[property];
  //     } else {
  //       throw new ReferenceError("Property \"" + property + "\" does not exist.");
  //     }
  //   }
  // });
  //
  // proxy.name // "张三"
  // person.name = 'yyyyyy';
  // console.log(proxy.name);
  // console.log(person.name);
  // console.log(person.age);//undefined
  // proxy.age // 抛出一个错误
}
// {
//   let target = {
//     foo: "Welcome, foo"
//   }
//   let proxy = new Proxy(target, {
//     get(target,name,receiver) {
//         console.log(receiver);
//         return name in target ? target[name] : `Hello, ${name}`
//     }
//   })
//   proxy.foo   === "Welcome, foo"
//   proxy.world === "Hello, world"
// }

// {
//   /**
//    * [读取负索引的数组的值]
//    * @param  {[type]} elements [description]
//    * @return {[type]}          [description]
//    */
//   function createArray(...elements) {
//     let target = [];
//     target.push(...elements);
//     let handler = {
//       get(target, propKey, receiver) {
//         let index = Number(propKey);
//         if (index < 0) {
//           propKey = String(target.length + index);
//         }
//         return Reflect.get(target, propKey, receiver);
//       }
//     };
//     return new Proxy(target, handler);
//   }
//   let arr = createArray('a','b','c','d');
//   console.log(arr[-2]);
// }

// {
//   const proxy = new Proxy({}, {
//     get: function(target, property, receiver) {
//       console.log(receiver);
//       return receiver;
//     }
//   });
//   proxy.getReceiver === proxy // true
// }

// {
//   var proto = {};
//   var p = new Proxy({}, {
//     getPrototypeOf(target) {
//       return proto;
//     }
//   });
//   console.log(Object.getPrototypeOf(p));
// }

{
  //   var p = new Proxy({},{
  //     isExtensible:function (target) {
  //       return true;
  //     }
  //   })
  //  console.log(Object.isExtensible(p))
}
// {
//   let target = { _bar: "foo", _prop: "bar", prop: "baz" };
//   let handler = {
//     ownKeys(target) {
//       return Reflect.ownKeys(target).filter(key => key[0] !== "_");
//     }
//   };
//   let proxy = new Proxy(target, handler);
//   for (let key of Object.keys(proxy)) {
//     console.log(target[key]);
//   }
// }
// {
//   const _name = new WeakMap();
//   class Person {
//     constructor(name) {
//       _name.set(this, name);
//     }
//     get name() {
//       return _name.get(this);
//     }
//   }
//   const jane = new Person("Jane");
//   console.log(jane.name);
//   jane.name; // 'Jane'
//   const proxy = new Proxy(jane, {});
//   console.log(proxy.name);
//   proxy.name; // undefined
// }

{
  // function createValidator(target, validator) {
  //   return new Proxy(target, {
  //     _validator: validator,
  //     set(target, key, value, proxy) {
  //       if (target.hasOwnProperty(key)) {
  //         let validator = this._validator[key];
  //         if (!!validator(value)) {
  //           return Reflect.set(target, key, value, proxy);
  //         } else {
  //           throw Error(`Cannot set ${key} to ${value}. Invalid.`);
  //         }
  //       } else {
  //         throw Error(`${key} is not a valid property`);
  //       }
  //     }
  //   });
  // }
  //
  // const personValidators = {
  //   name(val) {
  //     return typeof val === "string";
  //   },
  //   age(val) {
  //     return typeof age === "number" && age > 18;
  //   }
  // };
  // class Person {
  //   constructor(name, age) {
  //     this.name = name;
  //     this.age = age;
  //     return createValidator(this, personValidators);
  //   }
  // }
  //
  // const bill = new Person("Bill", 25);

  // 以下操作都会报错
  // bill.name = 0;
  // bill.age = "Bill";
  // bill.age = 15;
  // bill.name = 'yyyyy';
  // console.log(bill.name)
}
{
  //使用 Proxy 模拟类型检查，检查函数是否接收了类型和数量都正确的参数
  // let obj = {
  //   pickyMethodOne: function(obj, str, num) {
  //     /* ... */
  //   },
  //   pickyMethodTwo: function(num, obj) {
  //     /*... */
  //   }
  // };

  // const argTypes = {
  //   pickyMethodOne: ["object", "string", "number"],
  //   pickyMethodTwo: ["number", "object"]
  // };

  // obj = new Proxy(obj, {
  //   get: function(target, key, proxy) {
  //     var value = target[key]; //pickyMethodOne
  //     return function(...args) {
  //       //...args => target, key, proxy
  //       var checkArgs = argChecker(key, args, argTypes[key]); //pickyMethodOne,{target, key, proxy},["object", "string", "number"]
  //       return Reflect.apply(value, target, args); //pickyMethodOne,obj,{target, key, proxy}
  //     };
  //   }
  // });
  // function argChecker(name, args, checkers) {
  //   for (var idx = 0; idx < args.length; idx++) {
  //     var arg = args[idx]; //target => object   key => string   proxy => number
  //     var type = checkers[idx];
  //     if (!arg || typeof arg !== type) {
  //       console.warn(
  //         `You are incorrectly implementing the signature of ${name}. Check param ${idx +
  //           1}`
  //       );
  //     }
  //   }
  // }

  // obj.pickyMethodOne();
  // // > You are incorrectly implementing the signature of pickyMethodOne. Check param 1
  // // > You are incorrectly implementing the signature of pickyMethodOne. Check param 2
  // // > You are incorrectly implementing the signature of pickyMethodOne. Check param 3

  // obj.pickyMethodTwo("wopdopadoo", {});
  // // > You are incorrectly implementing the signature of pickyMethodTwo. Check param 1

  // // No warnings logged
  // obj.pickyMethodOne({}, "a little string", 123);
  // obj.pickyMethodOne(123, {});
}

{
  // let api = {
  //   _apiKey: '123abc456def',
  //   getUsers: function() {},
  //   getUser: function(userId) {},
  //   setUser: function(userId, config) {}
  // };
  // api = new Proxy(api, {
  //   get: function(api, key, proxy) {
  //     if (key.indexOf('_') > -1) {
  //       console.log('私有变量');
  //     }
  //     return Reflect.get(api, key, proxy);
  //   }
  // })
  // console.log(api)
}
